package com.mjf.spark.day05

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
 * 序列化
 *    -为什么要序列化
 *      因为在spark程序中，算子相关的操作在Executor上执行，算子之外的代码在Driver端执行，
 *      在执行有些算子的时候，需要使用到Driver里面定义的数据，这就涉及到了跨进程或者是跨节点
 *      之间的通讯。所以要求传递给Executor中的数组所属的类型必须实现Serializable接口
 *    -如果判断是否实现了序列化接口
 *      在作业job提交之前，其中有一行代码 val cleanF = sc.clean(f)，用于进行闭包检查，
 *      之所以叫闭包检查，是因为在当前函数的内部访问了外部函数的变量，属于闭包的形式。
 *      如果算子的参数是函数的形式，都会存在这种情况
 */
object Spark02_TestSerializable {
  def main(args: Array[String]): Unit = {

    // 创建SparkConf配置文件
    val conf = new SparkConf().setMaster("local[*]").setAppName("Spark02_TestSerializable")
    // 创建SparkContext对象
    val sc = new SparkContext(conf)

    // 创建对象
    val user1: User = new User
    user1.name = "lucy"
    val user2: User = new User
    user2.name = "jack"

    val rdd: RDD[User] = sc.makeRDD(List(user1, user2))

    // 算子相关的代码在executor执行，其他代码在driver执行
    rdd.foreach(println)

    // 关闭连接
    sc. stop()

  }
}

// 涉及到数据传输，对象必须是可序列化的
class User extends Serializable {
  var name : String = _

  override def toString = s"User($name)"
}
